package vg.modules.graph_comparison.components;

import vg.services.graph_view_manager.interfaces.graph_comparison.AGraphComparisonView;
import vg.services.graph_view_manager.interfaces.graph_comparison.IGraphComparisonAlgorithmObserver;
import vg.services.main_manager.VGMainServiceHelper;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.math.BigDecimal;

/**
 * Run dialog.
 * @author Timur Zolotuhin (tzolotuhin@gmail.com)
 */
public class RunDialog {
    // Mutex
    private static final Object generalMutex = new Object();

    public static void show(final AGraphComparisonView graphComparisonView) {
        if (!SwingUtilities.isEventDispatchThread()) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    synchronized (generalMutex) {
                        show(graphComparisonView);
                    }
                }
            });
        } else {
            synchronized (generalMutex) {
                // create components
                if (graphComparisonView == null)
                    return;

                final JProgressBar progressBar = new JProgressBar(0, 100);
                progressBar.setValue(0);
                progressBar.setStringPainted(true);

                final InnerDialog innerDialog = new InnerDialog(VGMainServiceHelper.userInterfaceManager.getMainFrame(), true, progressBar);
                innerDialog.addCancelListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        graphComparisonView.stopComparison();
                        innerDialog.setVisible(false);
                    }
                });

                Thread t = new Thread(new Runnable() {
                    private long startProcessTime;
                    private long finishProcessTime;
                    private BigDecimal countCases;

                    @Override
                    public void run() {
                        graphComparisonView.compare(new IGraphComparisonAlgorithmObserver() {
                        @Override
                        public void startProcess() {
                            startProcessTime = System.currentTimeMillis();
                        }

                        @Override
                        public void finishProcess() {
                            if (!SwingUtilities.isEventDispatchThread()) {
                                SwingUtilities.invokeLater(new Runnable() {
                                    @Override
                                    public void run() {
                                        finishProcess();
                                    }
                                });
                            } else {
                                // print info to log
                                finishProcessTime = System.currentTimeMillis();

                                long processTime = finishProcessTime - startProcessTime;
                                VGMainServiceHelper.logger.printInfo("Comparison time: " + (processTime / 1000.0f) + " sec.");
                                VGMainServiceHelper.logger.printInfo("Comparison count cases: " + countCases.toString());

                                // make invisible window
                                innerDialog.setVisible(false);
                            }
                        }

                        @Override
                        public void update4phase3(final BigDecimal currentCaseNumber, final BigDecimal upperBound) {
                            if (currentCaseNumber == null)
                                return;

                            if (!SwingUtilities.isEventDispatchThread()) {
                                SwingUtilities.invokeLater(new Runnable() {
                                    @Override
                                    public void run() {
                                        update4phase3(currentCaseNumber, upperBound);
                                    }
                                });
                            } else {
                                countCases = currentCaseNumber;

                                if (!upperBound.equals(new BigDecimal(0))) {
                                    BigDecimal percent = currentCaseNumber.divideToIntegralValue(upperBound);
                                    progressBar.setValue(percent.intValue());
                                }
                            }
                        }
                    });
                    }
                });
                t.setDaemon(true);
                t.start();

                innerDialog.setVisible(true);
                innerDialog.dispose();
            }
        }
    }

    private static class InnerDialog extends JDialog {
        private JPanel view = null;
        private JButton cancelButton = null;

        public InnerDialog(JFrame frame, boolean modal, JProgressBar progressBar) {
            super(frame, modal);

            view = new JPanel(new GridBagLayout());

            cancelButton = new JButton("Cancel");
            cancelButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    dispose();
                }
            });

            view.add(progressBar, new GridBagConstraints(0,0, 1,1, 1,1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5,5,5,5), 0,0));
            view.add(cancelButton, new GridBagConstraints(0,1, 1,1, 1,1, GridBagConstraints.EAST, GridBagConstraints.BOTH, new Insets(5,5,5,5), 0,0));

            getContentPane().add(view);

            pack();
            setLocationRelativeTo(frame);
            setVisible(false);
        }

        public void addCancelListener(ActionListener l) {
            cancelButton.addActionListener(l);
        }

        //public void removeCancelListener(ActionListener l) {
        //    cancelButton.removeActionListener(l);
        //}
    }
}
